package org.infodavid.common.services;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import junit.framework.Assert;

import org.jmock.Expectations;
import org.joda.time.DateTimeZone;
import org.junit.Test;

import org.infodavid.common.impl.model.criteria.ApplicationSettingsCriteriaImpl;
import org.infodavid.common.model.AbstractBeanTest;
import org.infodavid.common.model.ApplicationSettingsTest;
import org.infodavid.common.model.IApplicationSettings;
import org.infodavid.common.model.criteria.IApplicationSettingsCriteria;
import org.infodavid.common.persistence.ApplicationSettingsDataService;
import org.infodavid.common.services.ApplicationSettingsService;

/**
 * The Class ApplicationSettingsServiceTest.
 */
@SuppressWarnings({
	"null"
})
public class ApplicationSettingsServiceTest
    extends
    AbstractServiceTest<IApplicationSettings,IApplicationSettings,IApplicationSettingsCriteria,ApplicationSettingsDataService> {

	/** The delegate. */
	private final ApplicationSettingsTest delegate = new ApplicationSettingsTest(this);

	/**
	 * The Constructor.
	 */
	public ApplicationSettingsServiceTest() {
		super(ApplicationSettingsService.getInstance());
	}

	@Override
	public void setUp() throws Exception {
		super.setUp();

		getMockery().checking(new Expectations() {
			{
				allowing(contextMock).getSettings();
				will(returnValue(null));
			}
		});
	}

	/**
	 * See super class or interface. (non-Javadoc)
	 * @return the data service class
	 * @see org.infodavid.common.services.AbstractServiceTest#getDataServiceClass()
	 */
	@Override
	public Class<ApplicationSettingsDataService> getDataServiceClass() {
		return ApplicationSettingsDataService.class;
	}

	/**
	 * See super class or interface. (non-Javadoc)
	 * @see org.infodavid.common.services.AbstractServiceTest#buildCriteria()
	 */
	@Override
	public IApplicationSettingsCriteria buildCriteria() {
		final IApplicationSettingsCriteria criteria = new ApplicationSettingsCriteriaImpl();

		criteria.setProductNamePattern("name");

		return criteria;
	}

	/**
	 * Test find by name.
	 * @throws Exception the exception
	 */
	@Test
	public final void testFindByProduct() throws Exception {
		final IApplicationSettings value = populate(ITEMS_TO_INSERT).get(0);
		Exception exception = null;

		expectationsOnPersistenceSession();

		try {
			((ApplicationSettingsService)getService())
			    .findByProduct(getContextMock(), value.getProduct());
		}
		catch (final Exception e) {
			e.printStackTrace();
			exception = e;
		}

		Assert.assertNull("An exception occurs", exception);
		Assert.assertNotNull("Data is null", value);
		Assert.assertNotNull("Key is null", value.getKey());
	}

	/**
	 * Test testFindByName.
	 * @throws Exception the exception
	 */
	@Test
	public final void testFindByProductWithoutValue() throws Exception {
		Exception exception = null;

		expectationsOnPersistenceSession();

		try {
			((ApplicationSettingsService)getService()).findByProduct(getContextMock(), null);
		}
		catch (final Exception e) {
			e.printStackTrace();
			exception = e;
		}

		Assert.assertNotNull("An exception occurs", exception);
		Assert.assertEquals("Wrong exception", IllegalArgumentException.class, exception.getClass());
	}

	/**
	 * Test testFindByName.
	 * @throws Exception the exception
	 */
	@Test
	public final void testFindByProductUsingAnInvalidContext() throws Exception {
		final IApplicationSettings value = populate(ITEMS_TO_INSERT).get(0);
		Exception exception = null;

		expectationsOnPersistenceSession();

		try {
			((ApplicationSettingsService)getService()).findByProduct(null, value.getProduct());
		}
		catch (final Exception e) {
			e.printStackTrace();
			exception = e;
		}

		Assert.assertNotNull("An exception occurs", exception);
		Assert.assertEquals("Wrong exception", IllegalArgumentException.class, exception.getClass());
	}

	/**
	 * Test add.
	 * @throws Exception the exception
	 */
	@Test
	public final void testAddWithoutProduct() throws Exception {
		final IApplicationSettings value = create(1).get(0);
		Exception exception = null;

		expectationsOnPersistenceSession();

		value.setProduct(null);

		try {
			getService().add(getContextMock(), value);
		}
		catch (final Exception e) {
			e.printStackTrace();
			exception = e;
		}

		Assert.assertNotNull("An exception occurs", exception);
		Assert.assertEquals("Wrong exception", IllegalArgumentException.class, exception.getClass());
	}

	/**
	 * Test get entities.
	 * @throws Exception the exception
	 */
	@Test
	public void testGetEntitiesWithCriteria() throws Exception {
		final IApplicationSettings value = populate(ITEMS_TO_INSERT).get(0);
		final IApplicationSettingsCriteria criteria = buildCriteria();
		final List<IApplicationSettings> results = new ArrayList<IApplicationSettings>();
		Exception exception = null;

		expectationsOnPersistenceSession();
		expectationsOnSecureService();

		try {
			getService().findEntities(getContextMock(), results, criteria);
		}
		catch (final Exception e) {
			e.printStackTrace();
			exception = e;
		}

		Assert.assertNull("An exception occurs", exception);
		Assert.assertNotNull("Data is null", value);
		Assert.assertNotNull("Key is null", value.getKey());
	}

	/**
	 * Test get entities.
	 * @throws Exception the exception
	 */
	@Test
	public void testGetEntitiesWithCriteriaUsingAnInvalidContext() throws Exception {
		final IApplicationSettingsCriteria criteria = buildCriteria();
		final List<IApplicationSettings> results = new ArrayList<IApplicationSettings>();
		Exception exception = null;

		expectationsOnPersistenceSession();
		expectationsOnSecureService();

		try {
			getService().findEntities(null, results, criteria);
		}
		catch (final Exception e) {
			e.printStackTrace();
			exception = e;
		}

		Assert.assertNotNull("An exception occurs", exception);
		Assert.assertEquals("Wrong exception", IllegalArgumentException.class, exception.getClass());
	}

	/**
	 * Test get entities.
	 * @throws Exception the exception
	 */
	@Test
	public void testGetEntitiesWithCriteriaUsingAnInvalidCriteria() throws Exception {
		final IApplicationSettings value = populate(ITEMS_TO_INSERT).get(0);
		final List<IApplicationSettings> results = new ArrayList<IApplicationSettings>();
		Exception exception = null;

		expectationsOnPersistenceSession();
		expectationsOnSecureService();

		try {
			getService().findEntities(getContextMock(), results, null);
		}
		catch (final Exception e) {
			e.printStackTrace();
			exception = e;
		}

		Assert.assertNull("An exception occurs", exception);
		Assert.assertNotNull("Data is null", value);
		Assert.assertNotNull("Key is null", value.getKey());
	}

	/**
	 * Test get entities.
	 * @throws Exception the exception
	 */
	@Test
	public void testGetEntitiesWithCriteriaUsingAnInvalidList() throws Exception {
		populate(ITEMS_TO_INSERT).get(0);
		final IApplicationSettingsCriteria criteria = buildCriteria();
		Exception exception = null;

		expectationsOnPersistenceSession();
		expectationsOnSecureService();

		try {
			getService().findEntities(getContextMock(), null, criteria);
		}
		catch (final Exception e) {
			e.printStackTrace();
			exception = e;
		}

		Assert.assertNotNull("An exception occurs", exception);
		Assert.assertEquals("Wrong exception", IllegalArgumentException.class, exception.getClass());
	}

	/*
	 * (non-Javadoc)
	 * @see org.infodavid.common.persistence.AbstractDataServiceTest#getBeanTest()
	 */
	@Override
	protected AbstractBeanTest<IApplicationSettings> getBeanTest() {
		return delegate;
	}

	/**
	 * Test add.
	 * @throws Exception the exception
	 */
	@Test
	public final void testGetDefaultLocale() throws Exception {
		final IApplicationSettings value = populate(1).get(0);

		value.getProperties().addData(ApplicationSettingsService.DEFAULT_LOCALE_PROPERTY,
		    Locale.US.getLanguage());

		getSession().updateEntity(value, null);
		expectationsOnPersistenceSession();

		final Locale locale =
		    ((ApplicationSettingsService)getService()).getDefaultLocale(getContextMock());

		Assert.assertNotNull("No result", locale);
		Assert.assertEquals("Wrong result", Locale.US, locale);
	}

	/**
	 * Test add.
	 * @throws Exception the exception
	 */
	@Test
	public final void testGetDefaultLocaleWithoutSettings() throws Exception {
		populate(1).get(0);

		expectationsOnPersistenceSession();

		final Locale locale =
		    ((ApplicationSettingsService)getService()).getDefaultLocale(getContextMock());

		Assert.assertNotNull("No result", locale);
		Assert.assertEquals("Wrong result", Locale.getDefault(), locale);
	}

	/**
	 * Test add.
	 * @throws Exception the exception
	 */
	@Test
	public final void testGetDefaultLocaleUsingAnInvalidContext() throws Exception {
		Exception exception = null;

		expectationsOnPersistenceSession();

		try {
			((ApplicationSettingsService)getService()).getDefaultLocale(null);
		}
		catch (final Exception e) {
			e.printStackTrace();
			exception = e;
		}

		Assert.assertNotNull("No exception occurs", exception);
		Assert.assertEquals("Wrong exception", IllegalArgumentException.class, exception.getClass());
	}

	/**
	 * Test add.
	 * @throws Exception the exception
	 */
	@Test
	public final void testGetDefaultTimeZone() throws Exception {
		final IApplicationSettings value = populate(1).get(0);
		final int offsetHours = 8;

		value.getProperties().addData(ApplicationSettingsService.DEFAULT_TIME_ZONE_PROPERTY,
		    String.valueOf(offsetHours));

		getSession().updateEntity(value, null);

		expectationsOnPersistenceSession();

		final DateTimeZone tz =
		    ((ApplicationSettingsService)getService()).getDefaultTimeZone(getContextMock());

		Assert.assertNotNull("No result", tz);
		Assert.assertEquals("Wrong result", DateTimeZone.forOffsetHours(offsetHours).toTimeZone()
		    .getRawOffset(), tz.toTimeZone().getRawOffset());
	}

	/**
	 * Test add.
	 * @throws Exception the exception
	 */
	@Test
	public final void testGetDefaultTimeZoneWithoutSettings() throws Exception {
		populate(1).get(0);

		expectationsOnPersistenceSession();

		final DateTimeZone tz =
		    ((ApplicationSettingsService)getService()).getDefaultTimeZone(getContextMock());

		Assert.assertNotNull("No result", tz);
		Assert.assertEquals("Wrong result", DateTimeZone.getDefault(), tz);
	}

	/**
	 * Test add.
	 * @throws Exception the exception
	 */
	@Test
	public final void testGetDefaultTimeZoneUsingAnInvalidContext() throws Exception {
		Exception exception = null;

		expectationsOnPersistenceSession();

		try {
			((ApplicationSettingsService)getService()).getDefaultTimeZone(null);
		}
		catch (final Exception e) {
			e.printStackTrace();
			exception = e;
		}

		Assert.assertNotNull("An exception occurs", exception);
		Assert.assertEquals("Wrong exception", IllegalArgumentException.class, exception.getClass());
	}
}
